/*
Copyright (C) 2010 Copyright 2010 Google Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package jake2.tools;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;

public class Downloader implements Runnable {

	public static final String Q2_EXE_FILE_NAME = "q2-314-demo-x86.exe";
	
	static final String[] MIRRORS = {
		"ftp://ftp.fu-berlin.de/pc/msdos/games/idgames/idstuff/quake2/" + Q2_EXE_FILE_NAME,
		"ftp://ftp.cs.tu-berlin.de/pub/msdos/mirrors/ftp.idsoftware.com/quake2/" + Q2_EXE_FILE_NAME,
		"ftp://ftp.demon.co.uk/pub/mirrors/idsoftware/quake2/" + Q2_EXE_FILE_NAME,
		"ftp://ftp.fragzone.se/pub/spel/quake2/" + Q2_EXE_FILE_NAME,
		"ftp://ftp.idsoftware.com/idstuff/quake2/" + Q2_EXE_FILE_NAME,
		"ftp://ftp.gamers.org/pub/games/idgames2/idstuff/quake2/" + Q2_EXE_FILE_NAME
	};
	
	public static void main(String[] args) throws MalformedURLException, InterruptedException {
		if (new File("raw", "baseq2").exists()) {
			System.out.println("raw/baseq2 already exists; no need to download");
			return;
		}
		
		if ( new File(Q2_EXE_FILE_NAME).exists() ) { //TODO also verify the file CRC is valid
			System.out.println("A local version of " + Q2_EXE_FILE_NAME + "has been found");
			return;
		}
		
		int m0 = selectInitialMirror();
		for (int i = 0; i < MIRRORS.length * 2; i++) {
			Downloader download = new Downloader(MIRRORS[(i + m0) % MIRRORS.length]);
			Thread t = new Thread(download);
			t.start();
			t.join();
			if (download.ok) {
				return;
			}
		}
		throw new RuntimeException("Too many retries. Download failed.");
	}
	
	public static int selectInitialMirror() throws MalformedURLException {
		String domain = Locale.getDefault().getCountry();
		if (domain != null) {
			domain = domain.toLowerCase();
			if (domain.equals("us")) {
				domain = "com";
			} else if (domain.equals("gb")) {
				domain = "uk";
			}
			for (int i = 0; i < MIRRORS.length; i++) {
 				if ( new URL(MIRRORS[i]).getHost().endsWith( "." + domain) ) {
					return i;
				}
			}
		}
		return ((int) (Math.random() * 1000));
	}
	
	private final URL url;
	private byte[] buf = new byte[65536];
	boolean ok;
	
	public Downloader(String url) throws MalformedURLException {
		this.url = new URL(url);
		System.out.println("Trying mirror: " + url);
	}

	void copyStream(InputStream is, OutputStream os, boolean showProgress) throws IOException {
		int total = 0;
		int dots = 0;
		
		while (true) {
			int count = is.read(buf, 0, buf.length);
			if (count <= 0) {
				break;
			}
			total += count;
			if (showProgress) {
				if (total / 50000 > dots) {
					System.out.print(".");
					dots++;
				}
			}
			os.write(buf, 0, count);
		}
		os.close();
		is.close();
	}
	
	public void run() {
		try {	
			download();		
		} catch (IOException e) {
			System.out.println("Download and uncompression Failed");
		}
	}
	
	public File download() throws IOException {
			displayWarning();
		
			InputStream is = url.openStream();
			File tempFile = File.createTempFile("q2-temp", null);
			tempFile.deleteOnExit();
			System.out.print("Downloading");
			copyStream(is, new FileOutputStream(tempFile), true);
			
			System.out.println("Download finished; uncompressing");
			return tempFile;
	}
	
	private void displayWarning() {
		System.out.println("Downloading " + Q2_EXE_FILE_NAME + " might take few minutes for the installer.");
		System.out.println("It is faster to download it manually and put it in the root folder of the project.");
		System.out.println("You can try the following mirrors:");
		for (int i = 0; i < MIRRORS.length; i++) {
			System.out.println(MIRRORS[i]);
		}
	}
}
